package cn.iocoder.yudao.module.nginxui.service.eventsconfig;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.nginxui.dal.dataobject.config.NginxConfigDO;
import cn.iocoder.yudao.module.nginxui.service.config.NginxConfigService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.iocoder.yudao.module.nginxui.controller.admin.eventsconfig.vo.*;
import cn.iocoder.yudao.module.nginxui.dal.dataobject.eventsconfig.EventsConfigDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.nginxui.dal.mysql.eventsconfig.EventsConfigMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

import static cn.iocoder.yudao.module.nginxui.enums.ErrorCodeConstants.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Nginx events块配置 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class EventsConfigServiceImpl implements EventsConfigService {

    @Resource
    private EventsConfigMapper eventsConfigMapper;
    @Resource
    private NginxConfigService configService; // 注入主配置Service

    /**
     * 创建events配置 - 修复重复插入问题，添加事务
     */
    @Override
    @Transactional
    public Long createEventsConfig(EventsConfigSaveReqVO createReqVO) {
        // 1. 校验主配置是否存在
        if (createReqVO.getConfigId() == null) {
            throw exception(CONFIG_NOT_EXISTS); // 假设新增了CONFIG_ID_REQUIRED错误码
        }
        NginxConfigDO mainConfig = configService.getConfig(createReqVO.getConfigId());
        if (mainConfig == null) {
            throw exception(CONFIG_NOT_EXISTS);
        }

        // 2. 转换并设置默认值
        EventsConfigDO eventsConfig = BeanUtils.toBean(createReqVO, EventsConfigDO.class);
        setDefaultValues(eventsConfig);

        // 3. 只插入一次（修复重复插入问题）
        eventsConfigMapper.insert(eventsConfig);

        // 4. 同步到主配置content
        syncToMainConfig(mainConfig, eventsConfig);

        return eventsConfig.getId();
    }

    /**
     * 更新events配置 - 添加事务
     */
    @Override
    @Transactional
    public void updateEventsConfig(EventsConfigSaveReqVO updateReqVO) {
        // 1. 校验存在
        EventsConfigDO oldConfig = validateEventsConfigExists(updateReqVO.getId());

        // 2. 校验主配置
        if (updateReqVO.getConfigId() == null) {
            throw exception(CONFIG_ID_REQUIRED);
        }
        NginxConfigDO mainConfig = configService.getConfig(updateReqVO.getConfigId());
        if (mainConfig == null) {
            throw exception(CONFIG_NOT_EXISTS);
        }

        // 3. 转换并设置默认值（修复点：更新时也需要设置默认值）
        EventsConfigDO updateObj = BeanUtils.toBean(updateReqVO, EventsConfigDO.class);
        setDefaultValues(updateObj); // 新增：确保所有属性有默认值

        // 4. 更新配置
        eventsConfigMapper.updateById(updateObj);

        // 5. 同步到主配置
        syncToMainConfig(mainConfig, updateObj);
    }

    /**
     * 删除events配置 - 修复空指针问题，添加事务
     */
    @Override
    @Transactional
    public void deleteEventsConfig(Long id) {
        // 1. 先获取配置（修复删除后查询不到的问题）
        EventsConfigDO eventsConfig = validateEventsConfigExists(id);

        // 2. 获取主配置
        NginxConfigDO mainConfig = configService.getConfig(eventsConfig.getConfigId());
        if (mainConfig == null) {
            throw exception(CONFIG_NOT_EXISTS);
        }

        // 3. 从主配置中清除events块
        String content = clearEventsBlock(mainConfig.getContent());
        mainConfig.setContent(content);
        configService.updateConfigContent(mainConfig.getId(), content);

        // 4. 最后删除配置（确保前面操作成功）
        eventsConfigMapper.deleteById(id);
    }

    /**
     * 批量删除 - 添加事务
     */
    @Override
    @Transactional
    public void deleteEventsConfigListByIds(List<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        // 1. 先查询所有要删除的配置，用于同步主配置
        List<EventsConfigDO> configs = eventsConfigMapper.selectBatchIds(ids);
        if (CollUtil.isEmpty(configs)) {
            return;
        }

        // 2. 手动按主配置ID分组（替代CollUtil.groupBy）
        Map<Long, List<EventsConfigDO>> configGroup = new HashMap<>();
        for (EventsConfigDO config : configs) {
            Long configId = config.getConfigId();
            // 如果Map中没有该configId的列表，则创建一个
            if (!configGroup.containsKey(configId)) {
                configGroup.put(configId, new ArrayList<>());
            }
            // 将当前配置添加到对应的列表中
            configGroup.get(configId).add(config);
        }

        // 3. 按主配置ID批量清除events块
        for (Map.Entry<Long, List<EventsConfigDO>> entry : configGroup.entrySet()) {
            Long configId = entry.getKey();
            NginxConfigDO mainConfig = configService.getConfig(configId);
            if (mainConfig != null) {
                String content = clearEventsBlock(mainConfig.getContent());
                configService.updateConfigContent(configId, content);
            }
        }

        // 4. 批量删除
        eventsConfigMapper.deleteByIds(ids);
    }

    /**
     * 同步events配置到主配置content
     */
    private void syncToMainConfig(NginxConfigDO mainConfig, EventsConfigDO eventsConfig) {
        if (mainConfig == null || eventsConfig == null) {
            return; // 防御性判断
        }
        // 1. 同步events配置到主配置内容
        String newContent = syncEventsConfigToContent(mainConfig.getContent(), eventsConfig);
        // 2. 更新主配置content字段
        configService.updateConfigContent(mainConfig.getId(), newContent);
    }

    /**
     * 设置events配置默认值
     */
    private void setDefaultValues(EventsConfigDO eventsConfig) {
        if (eventsConfig == null) {
            return; // 防御性判断
        }
        if (eventsConfig.getWorkerConnections() == null) {
            eventsConfig.setWorkerConnections(1024);
        }
        if (eventsConfig.getMultiAccept() == null) {
            eventsConfig.setMultiAccept(0);
        }
        if (eventsConfig.getAcceptMutex() == null) {
            eventsConfig.setAcceptMutex(1);
        }
        if (eventsConfig.getAcceptMutexDelay() == null) {
            eventsConfig.setAcceptMutexDelay("500ms");
        }
        if (eventsConfig.getStatus() == null) {
            eventsConfig.setStatus(1);
        }
    }

    /**
     * 清除现有events块 - 优化正则表达式，不依赖特定注释
     */
    private String clearEventsBlock(String content) {
        if (content == null) {
            return "";
        }
        // 关键优化：匹配一个或多个"# 事件处理模块配置"注释（无论是否有空格/换行），再匹配events块
        Pattern pattern = Pattern.compile(
                "(?s)\\s*(#\\s*事件处理模块配置\\s*)+\\s*events\\s*\\{.*?}\\s*\\n?",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(content);
        String processedContent = matcher.replaceAll("");

        // 二次清理：单独清除可能残留的"# 事件处理模块配置"注释（无关联events块的情况）
        Pattern commentPattern = Pattern.compile(
                "(?m)^\\s*#\\s*事件处理模块配置\\s*$\\n?",
                Pattern.CASE_INSENSITIVE
        );
        processedContent = commentPattern.matcher(processedContent).replaceAll("");

        // 清理空行
        return processedContent.replaceAll("(?m)^\\s*$\\n?", "");
    }

    /**
     * 将events块插入到配置中 - 优化插入位置逻辑
     */
    private String insertEventsBlock(String content, String eventsBlock) {
        if (content == null || content.trim().isEmpty()) {
            return eventsBlock;
        }

        // 确保events块（含注释）与前面内容有换行分隔
        // 在eventsBlock前添加换行符，避免紧挨着前面的配置
        String formattedBlock = "\n" + eventsBlock;

        // 尝试在http块之前插入（最合理的位置）
        Pattern httpPattern = Pattern.compile("(\\s*)(http\\s*\\{)", Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
        Matcher httpMatcher = httpPattern.matcher(content);
        if (httpMatcher.find()) {
            return httpMatcher.replaceFirst(
                    "$1" + formattedBlock + "\n" +  // 插入带换行的events块
                            "$1$2"                        // 保留原http块
            );
        }

        // 尝试在全局配置（worker_processes/error_log/pid）之后插入
        Pattern globalPattern = Pattern.compile("(?s)(^.*?(worker_processes|error_log|pid).*?;\\s*)(\\n|$)",
                Pattern.CASE_INSENSITIVE);
        Matcher globalMatcher = globalPattern.matcher(content);
        if (globalMatcher.find()) {
            // 确保全局配置后有换行，再插入events块
            return globalMatcher.replaceFirst("$1\n" + formattedBlock + "\n");
        }

        // 都匹配不到时，添加到文件开头（但保持格式）
        return eventsBlock + "\n" + content;
    }

    /**
     * 将events配置同步到主配置内容中
     */
    public String syncEventsConfigToContent(String content, EventsConfigDO eventsConfig) {
        if (content == null) {
            content = "";
        }
        // 1. 清除现有events块配置
        content = clearEventsBlock(content);

        // 2. 如果配置未启用，直接返回
        if (eventsConfig == null || eventsConfig.getStatus() == 0) {
            return content;
        }

        // 3. 构建新的events块内容（使用Java 8兼容的非空判断）
        StringBuilder eventsContent = new StringBuilder();
        eventsContent.append("# 事件处理模块配置\n");
        eventsContent.append("events {\n");

        // 添加worker_connections（Java 8兼容写法）
        int workerConnections = (eventsConfig.getWorkerConnections() != null)
                ? eventsConfig.getWorkerConnections()
                : 1024;
        eventsContent.append("    # 每个工作进程的最大连接数\n");
        eventsContent.append("    worker_connections ").append(workerConnections).append(";\n\n");

        // 添加event_model（已做非空判断）
        if (eventsConfig.getEventModel() != null && !eventsConfig.getEventModel().trim().isEmpty()) {
            eventsContent.append("    # 事件模型（如epoll、kqueue等）\n");
            eventsContent.append("    use ").append(eventsConfig.getEventModel()).append(";\n\n");
        }

        // 添加multi_accept（Java 8兼容写法）
        int multiAccept = (eventsConfig.getMultiAccept() != null)
                ? eventsConfig.getMultiAccept()
                : 0;
        eventsContent.append("    # 是否允许同时接受多个连接（on/off）\n");
        eventsContent.append("    multi_accept ").append(multiAccept == 1 ? "on" : "off").append(";\n\n");

        // 添加accept_mutex（Java 8兼容写法）
        int acceptMutex = (eventsConfig.getAcceptMutex() != null)
                ? eventsConfig.getAcceptMutex()
                : 1;
        eventsContent.append("    # 是否开启accept_mutex锁（on/off）\n");
        eventsContent.append("    accept_mutex ").append(acceptMutex == 1 ? "on" : "off").append(";\n\n");

        // 添加accept_mutex_delay（已做非空判断）
        if (eventsConfig.getAcceptMutexDelay() != null && !eventsConfig.getAcceptMutexDelay().trim().isEmpty()) {
            eventsContent.append("    # accept_mutex锁的延迟时间\n");
            eventsContent.append("    accept_mutex_delay ").append(eventsConfig.getAcceptMutexDelay()).append(";\n");
        }

        eventsContent.append("}");

        // 4. 将新的events块添加到配置中
        return insertEventsBlock(content, eventsContent.toString());
    }

    /**
     * 校验events配置是否存在，并返回配置对象
     */
    private EventsConfigDO validateEventsConfigExists(Long id) {
        if (id == null) {
            throw exception(EVENTS_CONFIG_NOT_EXISTS); // 假设新增了此错误码
        }
        EventsConfigDO eventsConfig = eventsConfigMapper.selectById(id);
        if (eventsConfig == null) {
            throw exception(EVENTS_CONFIG_NOT_EXISTS);
        }
        return eventsConfig;
    }

    @Override
    public EventsConfigDO getEventsConfig(Long id) {
        return eventsConfigMapper.selectById(id);
    }

    @Override
    public PageResult<EventsConfigDO> getEventsConfigPage(EventsConfigPageReqVO pageReqVO) {
        return eventsConfigMapper.selectPage(pageReqVO);
    }
}
